﻿using System.Data;
using System.Runtime.Serialization;

namespace AppGene.DataModel
{
    /// <summary>
    /// The class provides a logical concept for a table.
    /// </summary>
    [DataContract]
    public class LogicalTable : IExtensibleDataObject
    {
        /// <summary>
        /// Creates a table with specific name.
        /// </summary>
        /// <param name="name"></param>
        public LogicalTable(string name)
        {
            this.Name = name;
        }

        #region IExtensibleDataObject Implementation
        private ExtensionDataObject extensionData_Value;

        ExtensionDataObject IExtensibleDataObject.ExtensionData
        {
            get
            {
                return extensionData_Value;
            }
            set
            {
                extensionData_Value = value;
            }
        }
        #endregion

        /// <summary>
        /// The database the table belongs to.
        /// </summary>
        public Database Database { get; internal set; }

        [DataMember]
        private LogicalColumnCollection columns;

        /// <summary>
        /// Get the table column collection.
        /// </summary>
        public LogicalColumnCollection Columns
        {
            get
            {
                if (columns == null)
                {
                    this.columns = new LogicalColumnCollection();
                }

                return columns;
            }
        }

        public LogicalIndex PrimaryKey
        { 
            get; 
        }

        [DataMember]
        private LogicalIndexCollection indexes;

        /// <summary>
        /// Get the table index collection.
        /// </summary>
        public LogicalIndexCollection Indexes
        {
            get
            {
                if (indexes == null)
                {
                    this.indexes = new LogicalIndexCollection();
                }

                return indexes;
            }
        }

        /// <summary>
        /// The name of the table.
        /// </summary>
        [DataMember]
        public string Name { get; private set; }

        /// <summary>
        /// The description of the table.
        /// </summary>
        [DataMember]
        public string Description { get; set; }

        /// <summary>
        /// Add a column in the table.
        /// </summary>
        /// <param name="column">The column instance.</param>
        /// <returns>The column instance.</returns>
        private LogicalColumn AddColumn(LogicalColumn column)
        {
            column.Table = this;
            this.Columns.Add(column);
            return column;
        }

        /// <summary>
        /// Add a column in the table.
        /// </summary>
        /// <param name="name">The column name.</param>
        /// <param name="nativeDataType">The native data type</param>
        /// <returns>The column instance.</returns>
        public LogicalColumn AddColumn(string name,
            string nativeDataType)
        {
            return AddColumn(new LogicalColumn(name, nativeDataType));
        }
        
        /// <summary>
        /// Add a column in the table.
        /// </summary>
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The column logical data type.</param>
        /// <returns>The column instance.</returns>
        public LogicalColumn AddColumn(string name,
            DbType dataType)
        {
            return AddColumn(new LogicalColumn(name, dataType));
        }

        /// <summary>
        /// Add a column in the table.
        /// </summary>
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The column logical data type.</param>
        /// <param name="length">The column length.</param>
        /// <returns>The column instance.</returns>
        public LogicalColumn AddColumn(string name,
            DbType dataType,
            int length)
        {
            return AddColumn(new LogicalColumn(name, dataType, length));
        }

        /// <summary>
        /// Add a column in the table.
        /// </summary>
        /// <param name="name">The column name.</param>
        /// <param name="dataType">The column logical data type.</param>
        /// <param name="precision">The column precision.</param>
        /// <param name="scale">The column scale.</param>
        /// <returns>The column instance.</returns>
        public LogicalColumn AddColumn(string name,
            DbType dataType,
            int precision,
            int scale)
        {
            return AddColumn(new LogicalColumn(name, dataType, precision, scale));
        }

        /// <summary>
        /// Add an index in the table.
        /// </summary>
        /// <param name="index">An index instance.</param>
        /// <returns>The added index instance.</returns>
        private LogicalIndex AddIndex(LogicalIndex index)
        {
            index.Table = this;
            this.Indexes.Add(index);
            return index;
        }

        /// <summary>
        /// Add an index in the table.
        /// </summary>
        /// <param name="columns"></param>
        /// <returns></returns>
        public LogicalIndex AddIndex(LogicalColumn[] columns)
        {
            return AddIndex(new LogicalIndex(columns));
        }

        /// <summary>
        /// Add a primary key in the table.
        /// </summary>
        /// <param name="columns"></param>
        /// <returns></returns>
        public LogicalIndex AddPrimaryKey(LogicalColumn[] columns)
        {
            LogicalIndex index = AddIndex(new LogicalIndex(columns));
            index.IsPrimaryKey = true;
            return index;
        }
    }
}
